use bytes::{Bytes, BytesMut};
use core::str;
use std::{fmt::Debug, ops::Deref};
use tools::{
	enum_generator,
	error::buf_err::{FromBufError, ToBufError},
	types::bufs::{FromBuf, ToBuf},
	utils::byte::{split_on, trim_split_on},
};
use tracing::error;

use crate::{untils::url::SipURI, CRLF, SEPARATOR, SIP_NAME, SIP_VERSION};

///此为sip逻辑的管理..
///
/// 可以通过调用listen_device()方法增加监听地址.
/// 第一次调用listen_device()方法.会生成一个协程,并且一直存在.
/// 此协程用来将sip消息与业务逻辑消息进行转换,
/// 每次新增加一个dialog时,将再生成一个协程,用来处理这个dialog的逻辑.但不增加协程用于处理事务
/// 需要进行会话时,会再生成一个协程用来处理会话方面.

#[derive(Debug, Clone, PartialEq, Eq, Copy)]
pub enum Method {
	Invite,
	Ack,
	Prack,
	Cancel,
	Bye,
	Register,
	Options,
	Info,
	Notify,
	Subscribe,
	Publish,
	Message,
	Update,
	Unknown,
}

impl ToBuf for Method {
	type Target = BytesMut;

	#[inline]
	fn write_to(&self, target: &mut Self::Target) -> Result<(), ToBufError> {
		if *self == Method::Unknown {
			return Err(ToBufError::new("sip方法未知."));
		}

		target.extend_from_slice(self.as_ref());

		Ok(())
	}
}

impl FromBuf for Method {
	type From = Bytes;

	fn from_buf_all(from: Self::From) -> Result<Self, FromBufError>
	where
		Self: Sized,
	{
		Ok(Self::from(from.deref()))
	}

	fn from_buf(from: &mut Self::From) -> Result<Self, FromBufError>
	where
		Self: Sized,
	{
		let buf = split_on(from, b' ');
		Self::from_buf_all(buf)
	}
}

enum_generator! {
	#[derive(Copy)]
	Response{
		Try(" 100 Trying",100),
		Ringing(" 180 Ringing",180),
		CallIsBeingForwarded(" 181 Call Is Being Forwarded",181),
		///被呼 叫方暂时不可用，但是服务器已确定将该呼叫转入等待队列
		Queued(" 182 Queued",182),
		SessionProgress(" 183 Session Progress",183),
		Ok(" 200 OK",200),
		MultipleChoices(" 300 Multiple Choices",300),
		MovedPermanently(" 301 Moved Permanently",301),
		MovedTemporarily(" 302 Moved Temporarily",302),
		UseProxy(" 305 Use Proxy",305),
		AlternativeService(" 380 Alternative Service",380),
		BadRequest(" 400 Bad Request",400),
		Unauthorized(" 401 Unauthorized",401),
		PaymentRequired(" 402 Payment Required",402),
		Forbidden(" 403 Forbidden",403),
		NotFound(" 404 Not Found",404),
		MethodNotAllowed(" 405 Method Not Allowed",405),
		NotAcceptable406(" 406 Not Acceptable",406),
		ProxyAuthenticationRequired(" 407 Proxy Authentication Required",407),
		RequestTimeout(" 408 Request Timeout",408),
		Conflict(" 409 Conflict",409),
		Gone(" 410 Gone",410),
		LengthRequired(" 411 Length Required",411),
		PreconditionFailed(" 412 Precondition Failed",412),
		RequestTooLong(" 414 Request-URI Too Long",414),
		UnsupportedMediaType(" 415 Unsupported Media Type",415),
		UnsupportedURIScheme(" 416 Unsupported URI Scheme",416),
		BadExtension(" 420 Bad Extension",420),
		ExtensionRequired(" 421 Extension Required",421),
		IntervalTooBrief(" 423 Interval Too Brief",423),
		TemporarilyUnavailable(" 480 Temporarily Unavailable",480),
		DoesNotExist(" 481 Call/Transaction Does Not Exist",481),
		LoopDetected(" 482 Loop Detected",482),
		TooManyHops(" 483 Too Many Hops",483),
		AddressIncomplete(" 484 Address Incomplete",484),
		Ambiguous(" 485 Ambiguous",485),
		BusyHere(" 486 Busy Here",486),
		RequestTerminated(" 487 Request Terminated",487),
		NotAcceptableHere(" 488 Not Acceptable Here",488),
		RequestPending(" 491 Request Pending",491),
		Undecipherable(" 493 Undecipherable",493),
		ServerInternalError(" 500 Server Internal Error",500),
		NotImplemented(" 501 Not Implemented",501),
		BadGateway(" 502 Bad Gateway",502),
		ServiceUnavailable(" 503 Service Unavailable",503),
		ServerTimeout(" 504 Gateway Time-out",504),
		VersionNotSupported(" 505 Version Not Supported",505),
		MessageTooLarge(" 513 Message Too Large",513),
		BusyEverywhere(" 600 Busy Everywhere",600),
		Decline(" 603 Decline",603),
		DoesNotExistAnywhere(" 604 Does Not Exist Anywhere",604),
		NotAcceptable606(" 606 Not Acceptable",606),
	}
}

impl ToBuf for Response {
	type Target = BytesMut;

	#[inline]
	fn write_to(&self, target: &mut Self::Target) -> Result<(), ToBufError> {
		target.extend_from_slice(self.as_bytes());

		Ok(())
	}
}

impl From<&[u8]> for Response {
	fn from(s: &[u8]) -> Self {
		match s {
			b"100" => Response::Try,
			b"180" => Response::Ringing,
			b"181" => Response::CallIsBeingForwarded,
			b"182" => Response::Queued,
			b"183" => Response::SessionProgress,
			b"200" => Response::Ok,
			b"300" => Response::MultipleChoices,
			b"301" => Response::MovedPermanently,
			b"302" => Response::MovedTemporarily,
			b"305" => Response::UseProxy,
			b"380" => Response::AlternativeService,
			b"400" => Response::BadRequest,
			b"401" => Response::Unauthorized,
			b"402" => Response::PaymentRequired,
			b"403" => Response::Forbidden,
			b"404" => Response::NotFound,
			b"405" => Response::MethodNotAllowed,
			b"406" => Response::NotAcceptable406,
			b"407" => Response::ProxyAuthenticationRequired,
			b"408" => Response::RequestTimeout,
			b"409" => Response::Conflict,
			b"410" => Response::Gone,
			b"411" => Response::LengthRequired,
			b"412" => Response::PreconditionFailed,
			b"414" => Response::RequestTooLong,
			b"415" => Response::UnsupportedMediaType,
			b"416" => Response::UnsupportedURIScheme,
			b"420" => Response::BadExtension,
			b"421" => Response::ExtensionRequired,
			b"423" => Response::IntervalTooBrief,
			b"480" => Response::TemporarilyUnavailable,
			b"481" => Response::DoesNotExist,
			b"482" => Response::LoopDetected,
			b"483" => Response::TooManyHops,
			b"484" => Response::AddressIncomplete,
			b"485" => Response::Ambiguous,
			b"486" => Response::BusyHere,
			b"487" => Response::RequestTerminated,
			b"488" => Response::NotAcceptableHere,
			b"491" => Response::RequestPending,
			b"493" => Response::Undecipherable,
			b"500" => Response::ServerInternalError,
			b"501" => Response::NotImplemented,
			b"502" => Response::BadGateway,
			b"503" => Response::ServiceUnavailable,
			b"504" => Response::ServerTimeout,
			b"505" => Response::VersionNotSupported,
			b"513" => Response::MessageTooLarge,
			b"603" => Response::Decline,
			b"600" => Response::BusyEverywhere,
			b"604" => Response::DoesNotExistAnywhere,
			b"606" => Response::NotAcceptable606,
			_ => Response::UnknownValue,
		}
	}
}

impl FromBuf for Response {
	type From = Bytes;

	fn from_buf_all(from: Self::From) -> Result<Self, FromBufError>
	where
		Self: Sized,
	{
		let res = Response::from(from.deref());
		Ok(res)
	}

	fn from_buf(from: &mut Self::From) -> Result<Self, FromBufError>
	where
		Self: Sized,
	{
		let buf = trim_split_on(from, b' ');
		Self::from_buf_all(buf)
	}
}

// ///通过挂断原因转换成sip响应码
// impl From<EndReason> for Response {
// 	fn from(s: EndReason) -> Self {
// 		match s {
// 			EndReason::NoCalledNum => Self::NotFound,
// 			_ => Self::TemporarilyUnavailable,
// 		}
// 	}
// }

///sip帧的标题解数据.有可能是请求,也有可能是响应.
/// 因为对于sip来说,可以双向通讯..所以同一时间的通讯都有可能是请求或响应
#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum Title {
	Request(RequestTitle),
	Response(ResponseTitle),
	Unknow,
}

impl Default for Title {
	fn default() -> Self {
		Title::Unknow
	}
}

impl Title {
	///固定的版本2.
	#[inline]
	pub(crate) fn with_resp_2(resp: Response) -> Self {
		Self::Response(ResponseTitle::new(resp, Version::V2_0))
	}

	pub(crate) fn version(&self) -> Version {
		match self {
			Title::Request(req) => req.version,
			Title::Response(resp) => resp.version,
			Title::Unknow => Version::V2_0,
		}
	}
}

impl ToBuf for Title {
	type Target = BytesMut;

	fn write_to(&self, target: &mut Self::Target) -> Result<(), ToBufError> {
		match self {
			Title::Request(req) => req.write_to(target),
			Title::Response(resp) => resp.write_to(target),
			Title::Unknow => Err(ToBufError::new("未指定有效的SipTitle值")),
		}
	}
}

impl FromBuf for Title {
	type From = Bytes;

	fn from_buf_all(from: Self::From) -> Result<Self, FromBufError>
	where
		Self: Sized,
	{
		let mut from = from.clone();

		//是以SIP/ 开始的话,那么这个帧则是响应,否则是请求
		if from[0..4] == *SIP_NAME {
			Ok(Self::Response(ResponseTitle::from_buf(&mut from)?))
		} else {
			Ok(Self::Request(RequestTitle::from_buf(&mut from)?))
		}
	}

	fn from_buf(from: &mut Self::From) -> Result<Self, tools::error::buf_err::FromBufError>
	where
		Self: Sized,
	{
		//是以SIP/ 开始的话,那么这个帧则是响应,否则是请求
		if from[0..4] == *SIP_NAME {
			Ok(Self::Response(ResponseTitle::from_buf(from)?))
		} else {
			Ok(Self::Request(RequestTitle::from_buf(from)?))
		}
	}
}

impl From<&[u8]> for Method {
	fn from(s: &[u8]) -> Self {
		match s {
			b"INVITE" | b"invite" => Method::Invite,
			b"REGISTER" | b"register" => Method::Register,
			b"ack" | b"ACK" => Method::Ack,
			b"bye" | b"BYE" => Method::Bye,
			b"cancel" | b"CANCEL" => Method::Cancel,
			b"options" | b"OPTIONS" => Method::Options,
			b"subscribe" | b"SUBSCRIBE" => Method::Subscribe,
			b"notify" | b"NOTIFY" => Method::Notify,
			b"prack" | b"PRACK" => Method::Prack,
			b"info" | b"INFO" => Method::Info,
			b"publish" | b"PUBLISH" => Method::Publish,
			b"message" | b"MESSAGE" => Method::Message,
			b"update" | b"UPDATE" => Method::Update,
			_ => Method::Unknown,
		}
	}
}

impl AsRef<[u8]> for Method {
	///取对应的字符串值
	fn as_ref(&self) -> &[u8] {
		match self {
			Method::Invite => b"INVITE",
			Method::Register => b"REGISTER",
			Method::Ack => b"ACK",
			Method::Bye => b"BYE",
			Method::Cancel => b"CANCEL",
			Method::Options => b"OPTIONS",
			Method::Subscribe => b"SUBSCRIBE",
			Method::Notify => b"NOTIFY",
			Method::Prack => b"PRACK",
			Method::Info => b"INFO",
			Method::Publish => b"PUBLISH",
			Method::Message => b"MESSAGE",
			Method::Update => b"UPDATE",
			Method::Unknown => {
				error!("不能为SipMethod::Unknown返回字符串..未知的sip方法");

				b""
			}
		}
	}
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Version {
	V2_0,
}

impl ToBuf for Version {
	type Target = BytesMut;

	#[inline]
	fn write_to(&self, target: &mut Self::Target) -> Result<(), ToBufError> {
		target.extend_from_slice(SIP_VERSION);

		Ok(())
	}
}

impl FromBuf for Version {
	type From = Bytes;

	fn from_buf_all(from: Self::From) -> Result<Self, FromBufError>
	where
		Self: Sized,
	{
		if from == SIP_VERSION {
			Ok(Version::V2_0)
		} else {
			let s = std::backtrace::Backtrace::capture();
			error!("传入的值:{from:?}..当前只支持Sip2.0版本..调用栈:{s}");
			Err(FromBufError::new("当前只支持Sip2.0版本"))
		}
	}

	fn from_buf(from: &mut Self::From) -> Result<Self, FromBufError>
	where
		Self: Sized,
	{
		let buf = split_on(from, b' ');
		Self::from_buf_all(buf)
	}
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct RequestTitle {
	version: Version,
	methon: Method,
	title_ptr: SipURI,
}

impl RequestTitle {
	pub fn new(version: Version, methon: Method, title_ptr: SipURI) -> Self {
		Self {
			version,
			methon,
			title_ptr,
		}
	}
}

impl ToBuf for RequestTitle {
	type Target = BytesMut;

	#[inline]
	fn write_to(&self, target: &mut Self::Target) -> Result<(), ToBufError> {
		self.methon.write_to(target)?;
		target.extend_from_slice(SEPARATOR);
		self.title_ptr.write_to(target)?;
		target.extend_from_slice(SEPARATOR);
		self.version.write_to(target)?;
		target.extend_from_slice(CRLF);

		Ok(())
	}
}

impl FromBuf for RequestTitle {
	type From = Bytes;

	#[inline]
	fn from_buf_all(from: Self::From) -> Result<Self, FromBufError>
	where
		Self: Sized,
	{
		Self::from_buf(&mut from.clone())
	}

	#[inline]
	fn from_buf(from: &mut Self::From) -> Result<Self, FromBufError>
	where
		Self: Sized,
	{
		let methon = Method::from_buf(from)?;
		let buf = trim_split_on(from, b' ');
		let title_ptr = SipURI::from_buf_all(buf)?;
		let version = Version::from_buf(from)?;
		Ok(Self {
			version,
			methon,
			title_ptr,
		})
	}
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ResponseTitle {
	resp: Response,
	version: Version,
}
impl ResponseTitle {
	#[inline]
	pub(crate) fn new(resp: Response, version: Version) -> Self {
		Self { resp, version }
	}
}
impl ToBuf for ResponseTitle {
	type Target = BytesMut;

	#[inline]
	fn write_to(&self, target: &mut Self::Target) -> Result<(), ToBufError> {
		self.version.write_to(target)?;
		target.extend_from_slice(SEPARATOR);
		self.resp.write_to(target)?;
		target.extend_from_slice(CRLF);

		Ok(())
	}
}

impl FromBuf for ResponseTitle {
	type From = Bytes;

	fn from_buf_all(from: Self::From) -> Result<Self, FromBufError>
	where
		Self: Sized,
	{
		let mut buf = from.clone();
		let buf_v = split_on(&mut buf, b' ');

		let version = Version::from_buf_all(buf_v)?;
		let resp = Response::from_buf_all(buf)?;

		Ok(Self { resp, version })
	}

	fn from_buf(from: &mut Self::From) -> Result<Self, FromBufError>
	where
		Self: Sized,
	{
		let version = Version::from_buf(from)?;
		let resp = Response::from_buf(from)?;

		Ok(Self { resp, version })
	}
}
